package com.intpro.demo.Controller;

import com.intpro.demo.DAO.AdminUser;
import com.intpro.demo.DAO.CommonRep;
import com.intpro.demo.DAO.User;
import com.intpro.demo.DAO.UserToken;
import com.intpro.demo.Service.AdminService;
import com.intpro.demo.Service.TokenService;
import com.intpro.demo.Service.UserService;
import com.intpro.demo.Service.VeryService;
import com.intpro.demo.Utils.AESToken;
import com.intpro.demo.Utils.CodeException;
import com.intpro.demo.Utils.DataFormat;
import com.intpro.demo.Utils.MyAnnotations.Authorization;
import com.intpro.demo.Utils.MyAnnotations.CurrentUser;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.util.Date;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@CrossOrigin
@RestController
@RequestMapping("api/user")
public class UserController
{

	@Autowired
	private UserService userService;
	@Autowired
	private AdminService adminService;
	@Autowired
	private TokenService tokenService;
	@Autowired
	private VeryService veryService;

	@Value("${xcloud.uploadPath}")
	private String uploadPath;

	@RequestMapping(value = "register", method = RequestMethod.POST)
	public CommonRep register(@RequestBody @Valid User user, BindingResult res) throws CodeException
	{
		if (res.hasErrors())
		{
			throw new CodeException(103, DataFormat.bindingErrorsFormat(res));
		}
		if (user.password == null || user.account == null || user.phone == null)
		{
			throw CodeException.NotNullErr();
		}
		if (user.account.equals("admin") || user.account.equals("admin1"))
		{
			AdminUser u = new AdminUser();
			u.account = user.account;
			u.password = user.password;
			adminService.addAdmin(u);
			return new CommonRep();
		}
		var v = veryService.findPhone(user.phone);
		if (v == null || !v.checked)
		{
			throw CodeException.NoCheckErr();
		}
		try
		{
			userService.addUser(user);
		} catch (Exception e)
		{
			throw CodeException.EmailRepeatErr();
		}
		return new CommonRep();
	}

	@RequestMapping(value = "login", method = {RequestMethod.POST})
	public CommonRep login(@RequestBody Map<String, String> req) throws CodeException
	{
		//String email = req.get("email");
		String account = req.get("account");
		String psw = req.get("password");
		if (account == null || psw == null)
		{
			throw CodeException.NotNullErr();
		}
		User user = null;
		String[] d = new String[2];
		try
		{
			if (account.equals("admin") || account.equals("admin1"))
			{
				var t = adminService.checkPswByAccount(account, psw);
				user = new User();
				user.id = t.id;
				user.account = t.account;
				d[1] = "admin";
			} else
			{
				user = userService.checkPswByAccount(account, psw);
			}
		} catch (Exception e)
		{
			throw CodeException.PasswordErr();
		}
		if (user == null)
		{
			throw CodeException.NoUserErr();
		}
		if (user.id == -1)
		{
			throw CodeException.PasswordErr();
		}
		CommonRep rep = new CommonRep();
		try
		{
			UserToken t = new UserToken();
			t.uid = user.id;
			t.createTime = new Date();
			t.token = AESToken.getToken(user);

			tokenService.updateToke(t);
			d[0] = t.token;
			rep.data = d;
		} catch (Exception e)
		{
			throw CodeException.PasswordErr();
		}

		return rep;
	}

	@Authorization
	@PostMapping("getMyInfo")
	public CommonRep getMyInfo(@CurrentUser User u)
	{
		CommonRep rep = new CommonRep();
		rep.data = u;
		return rep;
	}

	/*@GetMapping("getUserInfo/{uid}")
	public CommonRep getUserInfo(@PathVariable("uid") long uid)
	{
		CommonRep rep = new CommonRep();
		User u = userService.getUserById(uid);
		rep.data = u;
		return rep;
	}*/

	@GetMapping("getUserInfo/{account}")
	public CommonRep getUserInfo(@PathVariable("account") String account)
	{
		CommonRep rep = new CommonRep();
		User u = userService.getUserByAccount(account);
		rep.data = u;
		return rep;
	}

	@Authorization
	@RequestMapping(value = "changeUserInfo", method = {RequestMethod.POST})
	public CommonRep changeUserInfo(@CurrentUser User user, @RequestBody Map<String, String> req)
			throws CodeException
	{
		var nick = req.get("nickname");
		if (nick == null || nick.isEmpty())
		{
			throw CodeException.NotNullErr();
		}
		user.nickName = nick;
		userService.updateUser(user);
		return new CommonRep();
	}

	@Authorization
	@RequestMapping(value = "changePsw", method = {RequestMethod.POST})
	public CommonRep changePsw(@CurrentUser User user, @RequestBody Map<String, String> req)
			throws CodeException
	{
		var psw = req.get("psw");
		var oldpsw = req.get("oldpsw");
		if (oldpsw == null || psw == null)
		{
			throw CodeException.NotNullErr();
		}
		User u;
		try
		{
			u = userService.checkPswByAccount(user.account, oldpsw);
		} catch (Exception e)
		{
			throw CodeException.PasswordErr();
		}
		if (u == null || u.id == -1)
		{
			throw CodeException.PasswordErr();
		}
		try
		{
			user.password = AESToken.encrypt(psw);
		} catch (Exception e)
		{
			throw CodeException.PasswordErr();
		}

		userService.updateUser(user);
		return new CommonRep();

	}

	@Authorization
	@RequestMapping(value = "changePic", method = RequestMethod.POST)
	public CommonRep uploadImage(@CurrentUser User u, @RequestParam("file") MultipartFile file)
			throws CodeException
	{
		if (file == null || file.isEmpty())
		{
			throw CodeException.NotNullErr();
		}
		CommonRep rep = new CommonRep();
		try
		{
			u.picUrl = FileUploadController.saveFile(file, uploadPath, "pic/");
			userService.updateUser(u);
		} catch (Exception e)
		{
			throw CodeException.FileUploadErr();
		}
		return rep;
	}

}
